import prisma from '../config/prisma';
import {
  Department,
  CreateDepartmentRequest,
  UpdateDepartmentRequest,
  DepartmentWithChildren,
} from '../models/Department';
import { generateTimestampNumericUUID } from '../utils/uuid';

export class DepartmentService {
  // 获取所有部门
  static async getAllDepartments(): Promise<Department[]> {
    const departments = await prisma.department.findMany({
      where: {
        status: {
          not: 0,
        },
      },
      orderBy: [{ level: 'asc' }, { sort: 'asc' }, { createdAt: 'desc' }],
    });

    return departments as unknown as Department[];
  }

  // 获取部门树形结构
  static async getDepartmentTree(): Promise<DepartmentWithChildren[]> {
    const departments = await prisma.department.findMany({
      where: {
        status: {
          not: 0,
        },
      },
      orderBy: [{ level: 'asc' }, { sort: 'asc' }, { createdAt: 'desc' }],
    });

    // 构建树形结构
    const departmentMap = new Map<string, DepartmentWithChildren>();
    const rootDepartments: DepartmentWithChildren[] = [];

    // 初始化所有部门
    departments.forEach((department: any) => {
      const departmentWithChildren: DepartmentWithChildren = {
        ...department,
        children: [],
      };
      departmentMap.set(department.id, departmentWithChildren);
    });

    // 构建父子关系
    departments.forEach((department: any) => {
      const departmentWithChildren = departmentMap.get(department.id)!;
      if (department.parentId) {
        const parent = departmentMap.get(department.parentId);
        if (parent) {
          parent.children!.push(departmentWithChildren);
        }
      } else {
        rootDepartments.push(departmentWithChildren);
      }
    });

    return rootDepartments;
  }

  // 根据ID获取部门
  static async getDepartmentById(id: string): Promise<Department | null> {
    const department = await prisma.department.findUnique({
      where: {
        id: id,
      },
    });

    return department as Department | null;
  }

  // 根据编码获取部门
  static async getDepartmentByCode(code: string): Promise<Department | null> {
    const department = await prisma.department.findFirst({
      where: {
        code,
        status: {
          not: 0,
        },
      },
    });

    return department as Department | null;
  }

  // 创建部门
  static async createDepartment(
    departmentData: CreateDepartmentRequest
  ): Promise<Department> {
    const departmentId = generateTimestampNumericUUID();

    // 如果有父部门，计算层级
    let level = 1;
    if (departmentData.parentId) {
      const parentDepartment = await prisma.department.findUnique({
        where: { id: departmentData.parentId },
      });
      if (parentDepartment) {
        level = (parentDepartment.level || 1) + 1;
      }
    }

    const department = await prisma.department.create({
      data: {
        id: departmentId,
        name: departmentData.name,
        code: departmentData.code,
        description: departmentData.description,
        parentId: departmentData.parentId,
        level: departmentData.level || level,
        sort: departmentData.sort || 0,
        managerId: departmentData.managerId,
      },
    });

    return department as unknown as Department;
  }

  // 更新部门
  static async updateDepartment(
    departmentData: UpdateDepartmentRequest
  ): Promise<Department | null> {
    // 验证id是否存在
    if (!departmentData.id) {
      throw new Error('更新操作需要部门ID');
    }

    const updateData: Partial<UpdateDepartmentRequest> = {};

    // 动态构建更新字段，排除id字段
    Object.entries(departmentData).forEach(([key, value]) => {
      if (value !== undefined && key !== 'id') {
        // @ts-ignore
        updateData[key] = value as any;
      }
    });

    if (Object.keys(updateData).length === 0) return null;

    // 如果更新了父部门，重新计算层级
    if (updateData.parentId !== undefined) {
      if (updateData.parentId) {
        const parentDepartment = await prisma.department.findUnique({
          where: { id: updateData.parentId },
        });
        if (parentDepartment) {
          updateData.level = (parentDepartment.level || 1) + 1;
        }
      } else {
        updateData.level = 1;
      }
    }

    const department = await prisma.department.update({
      where: {
        id: departmentData.id,
      },
      data: updateData,
    });

    return department as unknown as Department;
  }

  // 删除部门（软删除）
  static async deleteDepartment(id: string): Promise<boolean> {
    try {
      // 检查是否有子部门
      const childDepartments = await prisma.department.findMany({
        where: {
          parentId: id,
          status: { not: 0 },
        },
      });

      if (childDepartments.length > 0) {
        throw new Error('不能删除有子部门的部门');
      }

      await prisma.department.update({
        where: { id },
        data: { status: 0 },
      });

      return true;
    } catch (error) {
      console.error('Error deleting department:', error);
      throw error;
    }
  }
}
